"""
本模块保存了一些变换的操作
"""
import numpy as np  # 使用numpy包中的数学函数与常量
from Huffman import keepzero  # 保留前导零

pai = np.pi
cos = np.cos
log = np.log


# 离散余弦变换
#记录C函数
def C(x):
    if x == 0:
        return 2 ** (-1 / 2)
    else:
        return 1

#开始DCT
def DCT(u, v, f):  # 二重求和--->两个for循环
    doublesigma = 0
    for i in range(8):
        for j in range(8):
            doublesigma = doublesigma + f[i][j] * cos((2 * i + 1) * u * pai / 16) * cos((2 * j + 1) * v * pai / 16)
    return 1 / 4 * C(u) * C(v) * doublesigma

def M128(u, v, f):  # 对与每个矩阵中的值减去128
    return f[u][v]-128


# 游程编码，计算长度，制作变长编码
def long(x):    #计算2的幂次，估计长度
    if x < 0:
        x = -x
    if x != 0:
        for k in range(1, int(x) + 1):
            if 2 ** (k - 1) <= x <= 2 ** k - 1:
                return k
    else:
        return 0

#计算编码，分正负讨论
def coded(x):
    if x > 0:
        return keepzero(long(x), int(x))
    elif x < 0:
        return keepzero(long(x), int(2 ** (long(x)) + x - 1))


#游程编码

def RunLenthCoding(l):
    s = []
    n = 0
    s.append(int(long(l[0])))
    s.append(coded(l[0]))      #DC系数单独列出
    for x in range(1, len(l)):   #处理AC系数，转化为 一个元组 + 一串二进制编码，结尾为（0,0）
        if l[x] != 0 or n == 15:
            s.append((n, long(l[x])))
            s.append(coded(l[x]))
            n = 0
        else:
            n = n + 1
            for z in range(x, len(l)):
                if l[z] != 0:
                    break
            else:
                s.append((0, 0))
                break
    return s    #返回编完码的list
